package paim.wingchun.testes.bench;


import java.math.BigDecimal;

public abstract class Benchmark {

    final String name;

    public Benchmark(String name) {
        this.name = name;
    }

    abstract int run(int iterations) throws Throwable;

    private BigDecimal time() {
        try {
            int nextI = 1;
            int i;
            long duration;
            do {
                i = nextI;
                long start = System.nanoTime();
                run(i);
                duration = System.nanoTime() - start;
                nextI = (i << 1) | 1;
            }
            while ( duration < 100000000 && nextI > 0 );
            return new BigDecimal((duration) * 1000 / i).movePointLeft(3);
        }
        catch ( Throwable e ) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String toString() {
        return name + "\t" + time() + " ns";
    }

    public static void main(String[] args) throws Exception {
        Benchmark[] benchmarks = { new Benchmark("int multiplication") {

            @Override
            int run(int iterations) throws Throwable {
                int x = 1;
                for ( int i = 0; i < iterations; i++ ) {
                    x *= 3;
                }
                return x;
            }
        }, new Benchmark("short multiplication") {

            @Override
            int run(int iterations) throws Throwable {
                short x = 0;
                for ( int i = 0; i < iterations; i++ ) {
                    x *= 3;
                }
                return x;
            }
        }, new Benchmark("byte multiplication") {

            @Override
            int run(int iterations) throws Throwable {
                byte x = 0;
                for ( int i = 0; i < iterations; i++ ) {
                    x *= 3;
                }
                return x;
            }
        }, new Benchmark("int[] traversal") {

            @Override
            int run(int iterations) throws Throwable {
                int[] x = new int[iterations];
                for ( int i = 0; i < iterations; i++ ) {
                    x[i] = i;
                }
                return x[x[0]];
            }
        }, new Benchmark("short[] traversal") {

            @Override
            int run(int iterations) throws Throwable {
                short[] x = new short[iterations];
                for ( int i = 0; i < iterations; i++ ) {
                    x[i] = (short) i;
                }
                return x[x[0]];
            }
        }, new Benchmark("byte[] traversal") {

            @Override
            int run(int iterations) throws Throwable {
                byte[] x = new byte[iterations];
                for ( int i = 0; i < iterations; i++ ) {
                    x[i] = (byte) i;
                }
                return x[x[0]];
            }
        }, };

        for ( Benchmark bm : benchmarks ) {
            System.out.println(bm);
        }
    }
}
